import amara, time
from Ft.Xml.Xslt import Transform
from Ft.Xml import Parse
from pkg_resources import resource_string
from wsgiappclient.utils import setup_xslt_params, fixup_characters
from wsgiappclient.middleware import XHTML_NS, ATOM10_NS, AC_NS, COMMON_PREFIXES
from wsgiappclient import uuid


class ClientAtomEntry(object):

    def __init__(self, data, author=None):
        self.rules = [amara.binderytools.ws_strip_element_rule(u'/*')]
        self.data = data
        self.author = self.create_author(author)
        for k, v in data.items():
            if '${atom_' not in v:
                self.data[k] = v
        #self.entry_xml = self.create(self.data)
        #self.invalid = self.valid(self.entry_xml)

    def fixup_xhtml(self, data):
        items = ['atom_summary', 'atom_content']
        for k in items:
            xhtml = amara.create_document(u'div', ns=XHTML_NS)
            xhtml.div.xml_append_fragment(fixup_characters(data[k]))
            data[k] = [xhtml.div]

    def create_author(self, a):
        try:
            doc = amara.parse(a, prefixes=COMMON_PREFIXES)
            return doc.author.xml()
        except:
            return a

    def create(self, data):
        doc = self.new_entry_template()
        if data.get('atom_title') and data.get('atom_content'):
            self.add_atom_title(data['atom_title'], doc)
            self.add_atom_content(data['atom_content'], doc)
        if data.get('atom_summary'):
            if data['atom_summary'] != '':
                self.add_atom_summary(data['atom_summary'], doc)
        return doc.xml()

    def edit(self, original, data):
        """
        Currently, only updating:
            atom:content
            atom:summary
            atom:title
            atom:updated
        """
        doc = amara.parse(original,
                          prefixes=COMMON_PREFIXES,
                          rules=self.rules)
        for k, v in data.items():
            method = 'add_%s' % k
            if hasattr(self, method):
                getattr(self, method)(v, doc)
        return doc.xml()

    def add_atom_title(self, new_title, doc):
        if new_title != '':
            if not hasattr(doc.entry, 'title'):
                doc.entry.xml_append(doc.xml_create_element(u'title', ATOM10_NS))
            if str(doc.entry.title) != new_title:
                doc.entry.title = unicode(new_title)

    def add_atom_updated(self, updated, doc):
        if updated:
            # try to parse it...
            try:
                # this just wrapps dateutils
                date = amara.binderytools.dateparse(updated)
                doc.entry.updated = unicode(updated)
            except ValueError, e:
                pass

    def add_atom_author_name(self, name, doc):
        if name:
            if hasattr(doc.entry, 'author'):
                if hasattr(doc.entry.author, 'name'):
                    old_name = doc.entry.author.name
                    doc.entry.author.xml_remove_child(old_name)
            else:
                doc.entry.xml_append(doc.xml_create_element(u'author', ATOM10_NS))
            doc.entry.author.xml_append(
                doc.xml_create_element(u'name', ATOM10_NS, content=unicode(name)))

    def add_atom_author_uri(self, uri, doc):
        if uri:
            if hasattr(doc.entry, 'author'):
                if hasattr(doc.entry.author, 'uri'):
                    old_uri = doc.entry.author.uri
                    doc.entry.author.xml_remove_child(old_uri)
            else:
                doc.entry.xml_append(doc.xml_create_element(u'author', ATOM10_NS))
            doc.entry.author.xml_append(
                doc.xml_create_element(u'uri', ATOM10_NS, content=unicode(uri)))

    def add_atom_author_email(self, email, doc):
        if email:
            if hasattr(doc.entry, 'author'):
                if hasattr(doc.entry.author, 'email'):
                    old_email = doc.entry.author.email
                    doc.entry.author.xml_remove_child(old_email)
            else:
                doc.entry.xml_append(doc.xml_create_element(u'author', ATOM10_NS))
            doc.entry.author.xml_append(
                doc.xml_create_element(u'email', ATOM10_NS, content=unicode(email)))

    def add_atom_content(self, new_content, doc):
        """
        We just replace it if there is a value... This is dangerous,
        but at the moment it is the best we got:/
        TODO: fix this to check for empty elements potentially sent by rich text box
        """
        if new_content.strip() != '':
            # new_content = '<div xmlns="%s">%s</div>' % (XHTML_NS, new_content.strip())
            ac = amara.create_document(u'div', XHTML_NS)
            ac.div.xml_append_fragment(new_content)
            print "Testing new content"
            print 
            print ac.xml(indent=True)
            print 
            #c = amara.parse(new_content, rules=self.rules)
            #c = amara.parse(new_content)
            c = ac
            if hasattr(doc.entry, 'content'):
                if hasattr(doc.entry.content, 'div'):
                    old_div = doc.entry.content.div
                    doc.entry.content.xml_remove_child(old_div)
            else:
                doc.entry.xml_append(
                    doc.xml_create_element(
                        u'content', ATOM10_NS,
                        attributes={u'type' : u'xhtml'}))
            doc.entry.content.xml_append(c.div)

    def add_atom_summary(self, new_summary, doc):
        """
        We just replace it if there is a value... This is dangerous,
        but at the moment it is the best we got:/
        TODO: fix this to check for empty elements potentially sent by rich text box
        """
        if new_summary.strip() != '':
            print "Have new summary"
            # stupid tinymce bug...
            new_summary = new_summary.replace('<p>&nbsp;</p>', '').strip()
            content = '<div xmlns="%s">%s</div>' % (XHTML_NS, fixup_characters(new_summary))
            c = amara.parse(content)
            if hasattr(doc.entry, 'summary'):
                if hasattr(doc.entry.summary, 'div'):
                    old_div = doc.entry.summary.div
                    doc.entry.summary.xml_remove_child(old_div)
            else:
                doc.entry.xml_append(
                    doc.xml_create_element(
                        u'summary', ATOM10_NS,
                        attributes={u'type' : u'xhtml'}))
            doc.entry.summary.xml_append(c.div)


    def new_entry_template(self):
        ns = ATOM10_NS
        doc = amara.create_document(u'entry', ns, prefixes=COMMON_PREFIXES)
        doc.entry.xml_append_fragment(self.author)
        atom_id = doc.xml_create_element(u'id', ns, content=unicode(uuid.uuid1().urn))
        doc.entry.xml_append(atom_id)
        now = time.strftime('%Y-%m-%dT%H:%M:%SZ')
        atom_updated = doc.xml_create_element(u'updated', ns, content=unicode(now))
        atom_published = doc.xml_create_element(u'published', ns, content=unicode(now))
        doc.entry.xml_append(atom_updated)
        doc.entry.xml_append(atom_published)
        return doc

    def validate(self, entry_xml):
        doc = amara.parse(entry_xml, prefixes=COMMON_PREFIXES)
        errors = {}
        if hasattr(doc.entry, 'title'):
            if not str(doc.entry.title).strip():
                errors['atom_title'] = '*'

        if hasattr(doc.entry, 'author'):
            if not str(doc.entry.author.name):
                errors['atom_author'] = '*'

        if hasattr(doc.entry, 'content'):
            if not str(doc.entry.content).strip():
                errors['atom_content'] = '*'

        return errors
